import React, { useMemo, useRef, memo } from 'react';
import Animated from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';
import { useAdaptiveSheetGestureHandlers, useAdaptiveSheetInternal } from '../../hooks';
import { GESTURE_SOURCE } from '../../constants';
import type { AdaptiveSheetDraggableViewProps } from './types';

const AdaptiveSheetDraggableViewComponent = ({
  gestureType = GESTURE_SOURCE.CONTENT,
  nativeGestureRef,
  refreshControlGestureRef,
  style,
  children,
  ...rest
}: AdaptiveSheetDraggableViewProps): JSX.Element => {
  const {
    enableContentPanningGesture,
    simultaneousHandlers: _providedSimultaneousHandlers,
    waitFor,
    activeOffsetX,
    activeOffsetY,
    failOffsetX,
    failOffsetY,
  } = useAdaptiveSheetInternal();
  const { contentPanGestureHandler, scrollablePanGestureHandler } = useAdaptiveSheetGestureHandlers();

  const panGestureRef = useRef<PanGestureHandler>(null);
  const gestureHandler = useMemo(
    () => (gestureType === GESTURE_SOURCE.CONTENT ? contentPanGestureHandler : scrollablePanGestureHandler),
    [gestureType, contentPanGestureHandler, scrollablePanGestureHandler],
  );
  const simultaneousHandlers = useMemo<React.Ref<unknown>[]>(() => {
    const refs: React.Ref<unknown>[] = [];

    if (nativeGestureRef) {
      refs.push(nativeGestureRef);
    }

    if (refreshControlGestureRef) {
      refs.push(refreshControlGestureRef);
    }

    if (_providedSimultaneousHandlers) {
      if (Array.isArray(_providedSimultaneousHandlers)) {
        refs.push(..._providedSimultaneousHandlers);
      } else {
        refs.push(_providedSimultaneousHandlers);
      }
    }

    return refs;
  }, [_providedSimultaneousHandlers, nativeGestureRef, refreshControlGestureRef]);

  return (
    <PanGestureHandler
      ref={panGestureRef}
      enabled={enableContentPanningGesture}
      simultaneousHandlers={simultaneousHandlers}
      shouldCancelWhenOutside={false}
      waitFor={waitFor}
      onGestureEvent={gestureHandler}
      activeOffsetX={activeOffsetX}
      activeOffsetY={activeOffsetY}
      failOffsetX={failOffsetX}
      failOffsetY={failOffsetY}>
      <Animated.View style={style} {...rest}>
        {children}
      </Animated.View>
    </PanGestureHandler>
  );
};

const AdaptiveSheetDraggableView = memo(AdaptiveSheetDraggableViewComponent);
AdaptiveSheetDraggableView.displayName = 'AdaptiveSheetDraggableView';

export default AdaptiveSheetDraggableView;
